#pragma once

#include "const.h"
#include "Singleton.h"
#include "ConfigManager.h"

#include <hiredis/hiredis.h>
#include <queue>

// TODO
class RedisConnectionPool : public Singleton<RedisConnectionPool>
{
	friend class Singleton<RedisConnectionPool>;

public:
	RedisConnectionPool(size_t poolSize, const char* host, unsigned short port, const char* pwd);
	~RedisConnectionPool() = default;

	redisContext* getConnection();
	void returnConnection(redisContext* context);
	void clearConnection();
	void close();

private:
	// 检测Redis连接的线程执行函数
	void checkThread();

private:
	const char* m_host;
	const char* m_pwd;
	unsigned short m_port;
	std::queue<redisContext*> m_connections;
	size_t m_pool_size;
	std::thread m_check_thread;
	std::atomic_bool m_b_stop;
	std::mutex m_mutex;

	std::condition_variable m_cond;
};

class RedisManager : public Singleton<RedisManager>, public std::enable_shared_from_this<RedisManager>
{
	friend class Singleton<RedisManager>;
public:
	~RedisManager() = default;

	// 获取key对应的value
	bool get(const std::string& key, std::string& value);
	// 设置key和value
	bool set(const std::string& key, const std::string& value);
	// 密码校验
	bool auth(const std::string& password);
	// 左侧push
	bool lPush(const std::string& key, const std::string& value);
	// 左侧pop
	bool lPop(const std::string& key, std::string& value);
	// 右侧push
	bool rPush(const std::string& key, const std::string& value);
	// 右侧pop
	bool rPop(const std::string& key, std::string& value);
	// HSet操作
	bool hSet(const std::string& key, const std::string& hkey, const std::string& value);
	bool hSet(const char* key, const char* hkey, const char* hvalue, size_t hvaluelen);
	// HGet操作
	std::string hGet(const std::string& key, const std::string& hkey);
	// hDel操作
	bool hDel(const std::string& key, const std::string& field);
	// Del 操作
	bool del(const std::string& key);
	// 判断键值是否存在
	bool existsKey(const std::string& key);
	// 关闭Redis连接池
	void close();

private:
	RedisManager();

private:
	std::unique_ptr<RedisConnectionPool> m_con_pool;
};

